#pragma once

#include "Misc/StdHead.h"
#include "Containers/Containers.h"
#include "Path/Path.h"
#include "Object/Object.h"
#include "Math/IntPoint.h"
#include "Render/Texture/TextureFormat.h"
#include "Texture2D.m.h"

class CRenderTexture2D;

RCLASS()
class WHENGINE_API RTexture2D : public RObject
{
    ROBJECT
public:

    struct STexture2DCreateInfo
    {
        TVector<uint8_t> RGBData;
        uint64_t ImagePitch;
        uint64_t ImageWidth;
        uint64_t ImageHeight;
        ETextureFormat ImageFormat   ;    
    };

    static  bool ParseImageFile(const SPath& ImageFilePath
        ,STexture2DCreateInfo& OutCreateInfo);
        
    static  TSharedObjectPtr<RTexture2D> CreateFromImage(const SPath& ImageFilePath,RObject* InOwner=nullptr);
    static  TSharedObjectPtr<RTexture2D> CreateFromPNGFileData(const TVector<uint8_t>& InPNGFileData,RObject* InOwner=nullptr);
    static  STexture2DCreateInfo CreateCreateInfoFromPNGFileData(const TVector<uint8_t>& InPNGFileData);
    static  TSharedObjectPtr<RTexture2D> CreateFromCreateInfo(STexture2DCreateInfo&& InCreateInfo,RObject* InOwner=nullptr);
    static  TSharedObjectPtr<RTexture2D> CreateFromRawData(TVector<uint8_t>&& InRGBData,uint64_t ImagePitch,const SIntPoint & ImageSize,ETextureFormat ImageFormat,RObject* InOwner=nullptr);
    static  void SaveToPNG(TSharedObjectPtr<RTexture2D>,const SPath& InPngFilePath);
    static  void SaveToPNGFileData(TSharedObjectPtr<RTexture2D> InImage,TVector<uint8_t>& OutPNGFileData);

    static  TSharedObjectPtr<RTexture2D> Resize(TSharedObjectPtr<RTexture2D>InOrignalImage,const SIntPoint& NewSize);
    static  void HorizontalFlip(TVector<uint8_t>& InOutData,int64_t ImageWidth,int64_t ImageHeight,int64_t ImagePitch,int64_t BytesPerPixel);
    static  void HorizontalFlip(TVector<uint8_t>& InOutData,int64_t ImageWidth,int64_t ImageHeight,int64_t ImagePitch,ETextureFormat Format);

    RTexture2D();
    ~RTexture2D();

public:

    SIntPoint GetSize()
    {
        return SIntPoint(Width,Height);
    }

    int64_t GetWidth()
    {
        return Width;
    }

    int64_t GetHeight()
    {
        return Height;
    }

    int64_t GetPitch()
    {
        return Pitch;
    }

    RFIELD()
    int64_t Width;
    RFIELD()
    int64_t Height;

    //Bytes num per image row
    RFIELD()
    int64_t Pitch;

    ETextureFormat GetFormat()
    {
        return Format;
    }
    
    RFIELD(SerializeAsBinary)
    TVector<uint8_t> Data;

    bool IsValid();

    void PostLoadFromAsset() override;
private:
    RFIELD()
    ETextureFormat Format=ETextureFormat::Undefined;

public:
    //after data changed , call this function to sync data to gpu
    void SyncToRenderThread();

    //get render texture
    std::shared_ptr<CRenderTexture2D> GetRenderTexture();
protected:
    std::shared_ptr<CRenderTexture2D> RenderTexture;

    bool bCanRender=false;

};
